#import "RNHistoryItemCell.h"
#import "RNConstants.h"
#import "NSBezierPath+MCAdditions.h"

static NSUInteger const minimumTitleWidth = 30;
static NSUInteger const tagPadding = 28;
static NSUInteger const tagElementPadding = 5;
static NSUInteger const tagHeight = 16;
static NSUInteger const tagBezelCornerRadius = 8;

static NSColor *backgroundColor, *backgroundColorHighlighted, *loggedDateBoxColor, *loggedDateBoxColorSelected;
static NSGradient *heartGradient, *notesGradient;
static NSGradient *tagsGradient, *tagsGradientHighlighted;
static NSColor *tagsBorderColor, *tagsBorderColorHighlighted, *tagsTextColorHighlighted, *tagsTextColor;
static NSColor *titleTextColor;
static NSShadow *embeddedObjectsInnerShadow; // Heart and notes icons

@implementation RNHistoryItemCell

@synthesize heartPath = heartPath_;
@synthesize notesPath = notesPath_;
@synthesize count = count_;
@synthesize notes = notes_;
@synthesize tags = tags_;
@synthesize favorite = favorite_;
@synthesize loggedDate = loggedDate_;
@synthesize loggedDateAttributes = loggedDateAttributes_;
@synthesize tagAttributes = tagAttributes_;
@synthesize titleAttributes = titleAttributes_;

+(void)initialize {
    backgroundColor = [NSColor colorWithCalibratedWhite:0.95f alpha:1.0f];
    backgroundColorHighlighted = [NSColor colorWithCalibratedRed:0.851 green:0.890 blue:0.957 alpha:1.000];
    loggedDateBoxColor = [NSColor colorWithCalibratedRed:0.819 green:0.860 blue:0.916 alpha:1.000];
    loggedDateBoxColorSelected = [NSColor colorWithCalibratedRed:0.789 green:0.831 blue:0.920 alpha:1.000];
    heartGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedRed:0.872 green:0.650 blue:0.647 alpha:1.000] endingColor:[NSColor colorWithCalibratedRed:0.894 green:0.773 blue:0.651 alpha:1.000]];
    embeddedObjectsInnerShadow = [[NSShadow alloc] init];
    [embeddedObjectsInnerShadow setShadowColor:[NSColor colorWithCalibratedWhite:0.0f alpha:0.5f]];
    [embeddedObjectsInnerShadow setShadowBlurRadius:3.0f];
    [embeddedObjectsInnerShadow setShadowOffset:NSMakeSize(0.0f, -1.0f)];
    notesGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedRed:0.897 green:0.881 blue:0.834 alpha:1.000] endingColor:[NSColor colorWithCalibratedRed:0.996 green:0.984 blue:0.924 alpha:1.000]];
    tagsGradient = [[NSGradient alloc] initWithStartingColor:[NSColor whiteColor] endingColor:[NSColor colorWithCalibratedRed:0.818 green:0.825 blue:0.853 alpha:1.000]];
    tagsGradientHighlighted = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedRed:0.958 green:0.973 blue:0.998 alpha:1.000] endingColor:[NSColor colorWithCalibratedRed:0.787 green:0.825 blue:0.880 alpha:1.000]];
    tagsBorderColor = [NSColor colorWithCalibratedWhite:0.663 alpha:1.000];
    tagsTextColorHighlighted = [NSColor colorWithCalibratedRed:0.402 green:0.409 blue:0.460 alpha:1.000];
    tagsTextColor = [NSColor colorWithCalibratedRed:0.471 green:0.477 blue:0.520 alpha:1.000];
    titleTextColor = [NSColor blackColor];
}

+ (BOOL)prefersTrackingUntilMouseUp {
    return YES;
}

-(id)initTextCell:(NSString *)theString {
    if (!(self = [super initTextCell:theString]))
        return nil;
        
    [self setHeartPath:RNHeartPathWithSize(NSMakeSize(RNDetailCellFavoriteWidth, RNGenericCellHeight))];
    [self setNotesPath:RNNotesPathWithSize(NSMakeSize(RNDetailCellNotesLength, RNGenericCellHeight))];

    [self setLineBreakMode:NSLineBreakByTruncatingTail];
    [self setFont:[NSFont systemFontOfSize:12.0f]];
    
    [self setTagAttributes:[NSDictionary dictionaryWithObject:[NSFont controlContentFontOfSize:11.0f] forKey:NSFontAttributeName]];    
    [self setLoggedDateAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont controlContentFontOfSize:11.0f], NSFontAttributeName, [NSColor colorWithCalibratedRed:0.496 green:0.558 blue:0.638 alpha:1.000], NSForegroundColorAttributeName, nil]];
    [self setTitleAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSFont systemFontOfSize:12.0f], NSFontAttributeName, [NSColor blackColor], NSForegroundColorAttributeName, nil]];
    
    return self;
}

-(NSArray *)keys {
    return [NSArray arrayWithObjects:@"title", @"count", @"notes", @"tags", nil];
}

- (id)objectValue {
    return [self dictionaryWithValuesForKeys:[self keys]];
}

-(void)setObjectValue:(id)obj {
    if (![obj isKindOfClass:[NSDictionary class]])
        return;
    [self setValuesForKeysWithDictionary:obj];
    [super setObjectValue:[obj valueForKey:RNTitleKey]];
}


#pragma mark -
#pragma mark Cell Behavior

-(BOOL)isSelectable {
    return NO;
}


#pragma mark -
#pragma mark Drawing

-(void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
    NSRect insetFrame = NSInsetRect(cellFrame, RNDetailViewBorderPadding, 0.0f);
    NSBezierPath *boundingPath = [NSBezierPath bezierPathWithRoundedRect:insetFrame xRadius:RNDetailViewCellCornerRadius yRadius:RNDetailViewCellCornerRadius];

    NSRect countBoxFrame = insetFrame;
    countBoxFrame.size.width = RNCountBoxWidth;
    NSBezierPath *itemCountBoxPath = RNCountBoxPathInRect(countBoxFrame);

    // Draw background
    NSColor *currentBackgroundColor = [self isHighlighted] ? backgroundColorHighlighted : backgroundColor;
    [currentBackgroundColor setFill];
    [boundingPath fill];
    
    NSColor *itemCountBoxColor = [self isHighlighted] ? loggedDateBoxColorSelected : loggedDateBoxColor;
    [itemCountBoxColor setFill];
    [itemCountBoxPath fill];

    // Draw logged date
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    NSString *loggedDateString = [dateFormatter stringFromDate:[self loggedDate]];
    NSAttributedString *loggedDateAttributedString = [[NSAttributedString alloc] initWithString:loggedDateString attributes:[self loggedDateAttributes]];
    [loggedDateAttributedString drawInRect:[self loggedDateFrameForCellFrame:cellFrame withAttributedString:loggedDateAttributedString]];

    // Draw tags
    [self drawTagsInRect:[self tagsRectForBounds:cellFrame]];
    
    // Draw favorite icon
    if ([[self favorite] boolValue]) {
        NSRect favoriteRect = [self favoriteRectForBounds:cellFrame];
        NSAffineTransform *translateTransform = [[NSAffineTransform alloc] init];
        [translateTransform translateXBy:NSMinX(favoriteRect) yBy:NSMinY(favoriteRect)];
        NSBezierPath *heartCopy = [[self heartPath] copy];
        [heartCopy transformUsingAffineTransform:translateTransform];
        NSGradient *currentHeartGradient = heartGradient;
        [currentHeartGradient drawInBezierPath:heartCopy angle:90];
        [heartCopy fillWithInnerShadow:embeddedObjectsInnerShadow];
    }
    
    // Draw notes icon
    if ([self notes]) {
        NSRect notesRect = [self notesRectForBounds:cellFrame];
        NSAffineTransform *translateTransform = [[NSAffineTransform alloc] init];
        [translateTransform translateXBy:NSMinX(notesRect) yBy:NSMinY(notesRect)];
        NSBezierPath *notesCopy = [[self notesPath] copy];
        [notesCopy transformUsingAffineTransform:translateTransform];
        [notesGradient drawInBezierPath:notesCopy angle:90];
        [notesCopy fillWithInnerShadow:embeddedObjectsInnerShadow];
    }
    
    // Draw Text
    NSMutableAttributedString *titleString = [[self attributedStringValue] mutableCopy];
    [titleString addAttribute:NSForegroundColorAttributeName value:titleTextColor range:NSMakeRange(0, [titleString length])];
    [titleString drawInRect:[self titleRectForBounds:cellFrame]];
}

- (NSAttributedString *)attributedStringValue {
    return [[NSAttributedString alloc] initWithString:[self stringValue] attributes:[self titleAttributes]];
}

-(void)drawTagsInRect:(NSRect)tagRect {
    if (![self tags])
        return;
    NSPoint currentTextPoint = NSMakePoint(NSMinX(tagRect) + (tagPadding / 2), NSMinY(tagRect) + 2.0f);
    NSRect bezelRect = tagRect;
    NSGradient *currentGradient = [self isHighlighted] ? tagsGradientHighlighted : tagsGradient;
    NSColor *textColor = [self isHighlighted] ? tagsTextColorHighlighted : tagsTextColor;
    NSColor *borderColor = [self isHighlighted] ? tagsBorderColorHighlighted : tagsBorderColor;
    NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:[self tagAttributes]];
    [attributes setValue:textColor forKey:NSForegroundColorAttributeName];
    for (NSString *tag in [self tags]) {
        NSAttributedString *attributedTag = [[NSAttributedString alloc] initWithString:tag attributes:attributes];
        CGFloat tagWidth = [attributedTag size].width;
        bezelRect.size.width = tagWidth + tagPadding;
        NSBezierPath *bezelPath = [NSBezierPath bezierPathWithRoundedRect:bezelRect xRadius:tagBezelCornerRadius yRadius:tagBezelCornerRadius];
        [currentGradient drawInBezierPath:bezelPath angle:90];
        [borderColor setStroke];
        [bezelPath stroke];
        [attributedTag drawAtPoint:currentTextPoint];
        bezelRect.origin.x += tagWidth + tagPadding + tagElementPadding;
        currentTextPoint.x += tagWidth + tagPadding + tagElementPadding;
    }
}

-(NSRect)titleRectForBounds:(NSRect)cellFrame {
    NSSize titleSize = [[self attributedStringValue] size];
    CGFloat insetY = (NSHeight(cellFrame) - titleSize.height) / 2;
    NSRect titleFrame = NSInsetRect(cellFrame, RNDetailViewBorderPadding, insetY);
    titleFrame.origin.x += RNCountBoxWidth + RNCountBoxPadding;
    titleFrame.size.width -= RNCountBoxWidth + RNCountBoxPadding;
    
//    if ([self tags] && [[self tags] count] > 0)
//        titleFrame.size.width = NSMinX([self tagsRectForBounds:cellFrame]) - RNGenericCellElementPadding - titleFrame.origin.x;
//    else if ([self notes])
//        titleFrame.size.width = NSMinX([self notesRectForBounds:cellFrame]) - RNGenericCellElementPadding - titleFrame.origin.x;
//    else if ([[self favorite] boolValue])
//        titleFrame.size.width = NSMinX([self favoriteRectForBounds:cellFrame]) - RNGenericCellElementPadding - titleFrame.origin.x;
//    else
//        titleFrame.size.width = NSMaxX(cellFrame) - RNGenericCellElementPadding;
//    titleFrame.size.height = titleSize.height;
//    titleFrame.origin.y += NSMidY(cellFrame) - NSMidY(titleFrame);
    return titleFrame;
}

-(NSRect)loggedDateFrameForCellFrame:(NSRect)cellFrame withAttributedString:(NSAttributedString *)loggedDateAttributedString {
    NSSize stringSize = [loggedDateAttributedString size];
    CGFloat originY = NSMidY(cellFrame) - (stringSize.height / 2);
    CGFloat originX = NSMinX(cellFrame) + RNDetailViewBorderPadding + RNCountBoxWidth - RNCountBoxPadding - stringSize.width;
    NSRect loggedDateFrame = NSMakeRect(originX, originY, stringSize.width, stringSize.height);
    return loggedDateFrame;
}

-(NSRect)favoriteRectForBounds:(NSRect)cellFrame {
    if (![[self favorite] boolValue])
        return NSZeroRect;
    return NSMakeRect((NSMaxX(cellFrame) - RNDetailCellFavoriteWidth - RNGenericCellEndPadding), NSMinY(cellFrame), RNDetailCellFavoriteWidth, NSHeight(cellFrame));
}

-(NSRect)notesRectForBounds:(NSRect)cellFrame {
    if (![self notes])
        return NSZeroRect;
    NSRect notesRect = cellFrame;
    notesRect.size.width = RNDetailCellNotesLength;
    if ([[self favorite] boolValue])
        notesRect.origin.x = NSMinX([self favoriteRectForBounds:cellFrame]) - RNGenericCellElementPadding - RNDetailCellNotesLength;
    else
        notesRect.origin.x = NSMaxX(cellFrame) - RNGenericCellEndPadding - RNDetailCellNotesLength;
    return notesRect;
}

-(NSRect)tagsRectForBounds:(NSRect)cellFrame {
    if (![self tags])
        return NSZeroRect;
    CGFloat totalWidth = 0;
    for (NSString *tag in [self tags]) {
        NSAttributedString *tagString = [[NSAttributedString alloc] initWithString:tag attributes:[self tagAttributes]];
        totalWidth += [tagString size].width;
        totalWidth += tagPadding;
    }
    totalWidth += ([[self tags] count] - 1) * tagElementPadding;
    CGFloat originX = NSMaxX(cellFrame) - RNGenericCellEndPadding - totalWidth;
    if ([self notes])
        originX = NSMinX([self notesRectForBounds:cellFrame]) - RNGenericCellElementPadding - totalWidth;
    else if ([[self favorite] boolValue])
        originX = NSMinX([self favoriteRectForBounds:cellFrame]) - RNGenericCellElementPadding - totalWidth;
    CGFloat originY = NSMinY(cellFrame) + (NSHeight(cellFrame) - tagHeight) / 2;
    return NSMakeRect(originX, originY, totalWidth, tagHeight);
}

- (NSColor *)highlightColorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
    return nil;
}

@end
